package com.smsc.headend.task.engine.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.util.NumberUtil;
import com.smsc.headend.module.data.dto.DataItemDTO;
import com.smsc.headend.module.data.entity.RdMeterReadsLp;
import com.smsc.headend.module.data.enums.CollectionSource;
import com.smsc.headend.task.engine.service.FronzenDataService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.assertj.core.util.Lists;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class FronzenDataServiceImpl implements FronzenDataService {
    @Override
    public List<RdMeterReadsLp> calculateMonthlyDataByMinMax(List<RdMeterReadsLp> dailyProfileData, long endTv) {
        Long maxTv = dailyProfileData.stream().map(RdMeterReadsLp::getTv).distinct().max(Comparator.comparingLong(Long::longValue)).get();
        Long minTv = dailyProfileData.stream().map(RdMeterReadsLp::getTv).distinct().min(Comparator.comparingLong(Long::longValue)).get();
        if (minTv.equals(maxTv)) {
            return Lists.emptyList();
        }
        List<RdMeterReadsLp> maxList = dailyProfileData.stream().filter(p -> p.getTv().equals(maxTv)).collect(Collectors.toList());
        List<RdMeterReadsLp> minList = dailyProfileData.stream().filter(p -> p.getTv().equals(minTv)).collect(Collectors.toList());

        List<RdMeterReadsLp> resultList = new ArrayList<>();
        maxList.stream().forEach(p ->
                {
                    RdMeterReadsLp minData = minList.stream().filter(q -> q.getDataItemId().equals(p.getDataItemId())).findAny().orElse(null);
                    if (minData == null) {
                        log.info("minListWithNoDataItem:{}", p.getDataItemId());
                        return;
                    }
                    RdMeterReadsLp result = new RdMeterReadsLp();
                    result.setValidity(999);
                    result.setDataItemId(p.getDataItemId());
                    result.setLpDataItemId(p.getDataItemId());
                    result.setTvUpdate(SystemClock.now() / DateUtils.MILLIS_PER_SECOND);
                    result.setSrc(CollectionSource.ODR.getSource());
                    result.setTv(endTv);
                    result.setMeterId(p.getMeterId());
                    result.setValue(getCalculateValue(p, minData, endTv));
                    resultList.add(result);
                }
        );
        return resultList;
    }

    @Override
    public List<RdMeterReadsLp> intersectWithCaptureObjList(List<RdMeterReadsLp> calculatedMonthlyData, List<DataItemDTO> dataItemCosemList) {
        if (CollectionUtil.isEmpty(calculatedMonthlyData)) {
            return Lists.emptyList();
        }
        List<RdMeterReadsLp> collect = calculatedMonthlyData.stream().filter(p -> dataItemCosemList.stream().filter(dl -> dl.getSubDataItemId().equals(p.getDataItemId())).findAny().isPresent()).collect(Collectors.toList());
        log.info("intersectBefore:{},After:{}", calculatedMonthlyData.size(), collect.size());
        return collect;
    }

    @Override
    public List<RdMeterReadsLp> handleSpecialDataItemData(List<RdMeterReadsLp> calculatedMonthlyData) {
        if (CollUtil.isNotEmpty(calculatedMonthlyData)) {
            for (RdMeterReadsLp data : calculatedMonthlyData) {
                // 日冻结数据项计算后对应月冻结的关系(020030006102 Total energy +A  -->> 1020030000102(Current monthly consumption energy))
                if (data.getDataItemId() == 1020030006102L) {
                    data.setDataItemId(1020030000102L);
                }
            }
        }
        return calculatedMonthlyData;
    }

    private String getCalculateValue(RdMeterReadsLp maxData, RdMeterReadsLp minData, long endTv) {
        if (!NumberUtil.isNumber(maxData.getValue()) || !NumberUtil.isNumber(minData.getValue())) {
            log.debug("lpDataNotNumber:returnMaxOne,{},{}", maxData, minData);
            return maxData.getValue();
        }
        try {
            long lastMonthOriSec = DateUtils.addMonths(new Date(endTv*DateUtils.MILLIS_PER_SECOND), -1).getTime() / DateUtils.MILLIS_PER_SECOND;
            Long monthTvGap = endTv - lastMonthOriSec;

            Long maxValue = Long.valueOf(maxData.getValue());
            Long minValue = Long.valueOf(minData.getValue());
            Long tvGap = maxData.getTv() - minData.getTv() ;
            Long valueGap = maxValue - minValue;

            Long finalValue = valueGap * monthTvGap / tvGap;
            log.info("lpDataSurmiseValue: {}, minValue:{},{},maxValue{},{}", finalValue, minData.getTv(), minData.getValue(), maxData.getTv(), maxData.getValue());
            return Convert.toStr(finalValue);
        } catch (Exception e) {
            return maxData.getValue();
        }
    }

//    public static void main(String[] args) {
//        RdMeterReadsLp maxData = new RdMeterReadsLp();
//        maxData.setValue("619593");
//        maxData.setTv(1654185600L);
//
//
//        RdMeterReadsLp minData = new RdMeterReadsLp();
//        minData.setValue("601976");
//        minData.setTv(1654012800L);
//
//        Long endTv = 1656604800L;
//
//        long lastMonthOriSec = DateUtils.addMonths(new Date(endTv*DateUtils.MILLIS_PER_SECOND), -1).getTime() / DateUtils.MILLIS_PER_SECOND;
//        Long monthTvGap = endTv - lastMonthOriSec;
//
//        Long maxValue = Long.valueOf(maxData.getValue());
//        Long minValue = Long.valueOf(minData.getValue());
//        Long tvGap = maxData.getTv() - minData.getTv() ;
//        Long valueGap = maxValue - minValue;
//
//        Long finalValue = valueGap * monthTvGap / tvGap;
//        log.info("lpDataSurmiseValue: {}, minValue:{},{},maxValue{},{}", finalValue, minData.getTv(), minData.getValue(), maxData.getTv(), maxData.getValue());
//    }

}
